package com.reebake.ideal.security.oauth2.client;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.xkcoding.http.config.HttpConfig;
import lombok.RequiredArgsConstructor;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.request.AuthDefaultRequest;
import me.zhyd.oauth.request.AuthRequest;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;

import java.util.Map;
import java.util.Set;

@RequiredArgsConstructor
public class JustAuthFactory {
    private final ClientRegistrationRepository clientRegistrationRepository;
    private Set<Class<?>> authRequestClzs = ClassUtil.scanPackage(ClassUtil.getPackage(AuthRequest.class));

    public AuthDefaultRequest create(String registrationId, String redirectUri) {
        ClientRegistration clientRegistration = clientRegistrationRepository.findByRegistrationId(registrationId);
        String clientId = clientRegistration.getClientId();
        String clientSecret = clientRegistration.getClientSecret();

        AuthConfig.AuthConfigBuilder authConfigBuilder = AuthConfig.builder();
        authConfigBuilder.clientId(clientId)
                .clientSecret(clientSecret)
                .redirectUri(redirectUri)
                ;
        Set<String> methodNames = ClassUtil.getDeclaredMethodNames(authConfigBuilder.getClass());
        Map<String, Object> configurationMetadata = clientRegistration.getProviderDetails().getConfigurationMetadata();
        if(MapUtil.isNotEmpty(configurationMetadata)) {
            for(Map.Entry<String, Object> entry : configurationMetadata.entrySet()) {
                String attributeName = entry.getKey();
                Object value = entry.getValue();
                if(methodNames.contains(attributeName)) {
                    ReflectUtil.invoke(authConfigBuilder, entry.getKey(), entry.getValue());
                }
            }
        }

        Class<?> authRequestClz = null;
        for(Class<?> clz : authRequestClzs) {
            if (clz.getSimpleName().toLowerCase().contains(registrationId.toLowerCase())) {
                authRequestClz = clz;
                break;
            }
        }
        Assert.notNull(authRequestClz, "没有找到对应的AuthRequest类");
        HttpConfig httpConfig = HttpConfig.builder().timeout(10000).build();// 延长超时时间
        AuthConfig authConfig = authConfigBuilder.httpConfig(httpConfig).build();
        return (AuthDefaultRequest) ReflectUtil.newInstance(authRequestClz, authConfig);
    }
}
